package com.demo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.demo.common.PageMessage;
import com.demo.core.exception.ParameterException;
import com.demo.dao.TeamCompositionDao;
import com.demo.dao.TeamProfileDao;
import com.demo.dao.UserDao;
import com.demo.domain.TeamComposition;
import com.demo.domain.TeamProfile;
import com.demo.domain.ro.TeamProfileRequest;
import com.demo.service.TeamProfileService;
import com.demo.utils.AuthorityUtils;
import com.demo.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.Date;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class TeamProfileServiceImpl extends ServiceImpl<TeamProfileDao, TeamProfile> implements TeamProfileService {

    @Autowired
    private TeamProfileDao teamProfileDao;

    @Autowired
    private TeamCompositionDao teamCompositionDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private StringUtils stringUtils;

    @Autowired
    private AuthorityUtils authorityUtils;

    /*CRUD*/
    @Override
    public TeamProfile getByTpId(Long tpId) throws ParameterException{
        if(tpId == null){
            throw new ParameterException("null");
        }
        TeamProfile teamProfile = teamProfileDao.selectById(tpId);
        if(teamProfile.getTpDelFlag() == 1){
            return null;
        }
        return teamProfile;
    }

    @Override
    public Integer insertTeamProfile(TeamProfile teamProfile) throws ParameterException {
        int row = 0;
        if(teamProfile.getTpUid()!=null && teamProfile.getTpUrealname()!=null && teamProfile.getTpTeamName()!=null && teamProfile.getTpProjectName()!= null && teamProfile.getTpContact()!=null && teamProfile.getTpNeedStudentNumber()!=null && teamProfile.getTpMemberNumber()!=null && teamProfile.getTpRegistrationDeadline()!=null){
            row = teamProfileDao.insert(teamProfile);
        }else{
            return null;
        }
        return row;
    }

    @Override
    public Integer updateTeamProfile(TeamProfile teamProfile) {
        int row = 0;
        if(teamProfile.getTpId()!=null && teamProfile.getTpUid()!=null && teamProfile.getTpUrealname()!=null && teamProfile.getTpTeamName()!=null && teamProfile.getTpProjectName()!= null && teamProfile.getTpContact()!=null && teamProfile.getTpDelFlag() == 0 && teamProfile.getTpNeedStudentNumber()!=null && teamProfile.getTpMemberNumber()!=null && teamProfile.getTpRegistrationDeadline()!=null){
            teamProfile.setTpDifference(teamProfile.getTpNeedStudentNumber()-teamProfile.getTpMemberNumber());
            row = teamProfileDao.updateById(teamProfile);
        }else{
            return null;
        }
        return row;
    }

    @Override
    public Integer deleteTeamProfileById(TeamProfile teamProfile) throws ParameterException {
        int row = 0;
        if(teamProfile.getTpId()!=null){
            row = teamProfileDao.deleteTeamProfileById(teamProfile);
        }

        return row;
    }

    @Override
    public List<TeamProfile> selectTeamProfileList(TeamProfile teamProfile) throws ParameterException {
        List<TeamProfile> teamProfileList = new ArrayList<>();
        if (teamProfile.getTpUid()!=null || teamProfile.getTpUrealname()!=null || teamProfile.getTpTeamName()!=null || teamProfile.getTpProjectName()!= null || teamProfile.getTpRegistrationDeadline()!=null) {
            teamProfileList=teamProfileDao.selectTeamProfileList(teamProfile.getTpUid(),teamProfile.getTpUrealname(),teamProfile.getTpTeamName(),teamProfile.getTpProjectName(),teamProfile.getTpRegistrationDeadline());
        }
        return teamProfileList;
    }

    @Override
    public List<TeamProfile> listAllTeamProfile(){
        List<TeamProfile> teamProfileList = teamProfileDao.listAllTeamProfile();
        return teamProfileList;
    }


    /**
     * 得到队伍详情信息
     *
     * @param tpId
     * @return
     */
    @Override
    public TeamProfile getTeamProfileById(Long tpId, Long uid) throws ParameterException {
        if (tpId == null || tpId < 0l) {
            throw new ParameterException("tpId非法或空");
        }
        if (uid == null || uid < 0l) {
            throw new ParameterException("uid非法或空");
        }
        LambdaQueryWrapper<TeamProfile> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //设置tpId进行搜索
        lambdaQueryWrapper.eq(TeamProfile::getTpId, tpId);
        TeamProfile teamProfile = teamProfileDao.selectOne(lambdaQueryWrapper);
        return teamProfile != null && teamProfile.getTpAlive() == 1 ? teamProfile : null;
    }

    /**
     * 得到uid未参与的队伍的信息
     *
     * @param uid
     * @param current
     * @param size
     * @return
     */
    @Override
    public List<TeamProfile> getNotInTeam(Long uid, int current, int size) throws ParameterException {
        if (current == 0 || size == 0) {
            throw new ParameterException("分页信息值为0");
        }
        if (uid <= 0l || uid == null || String.valueOf(uid).length() != 12) {
            throw new ParameterException("uid为空或值非法");
        }
        PageMessage<TeamProfile> pm = new PageMessage<>(current, size);
        if (uid != 0l) {
            //搜索
            List<TeamProfile> list = teamProfileDao.selectNotInTeam(uid);
            if (list != null && list.size() > 0) {
                //筛选出alive==1的队伍
                return selectAliveTeam(list);
            }
        }
        return null;

    }

    /**
     * 得到uid参与的所有队伍
     *
     * @param uid
     * @return
     * @throws ParameterException
     * @throws Exception
     */
    @Override
    public List<TeamProfile> getInTeam(Long uid) throws ParameterException, Exception {
        if (uid == null || uid < 0l) {
            throw new ParameterException("uid为空");
        }
        List<TeamProfile> list = teamProfileDao.selectInTeam(uid);
        //筛选出alive==1的队伍
        return list != null && list.size() > 0 ?
                selectAliveTeam(list) : null;
    }


    /**
     * 多条件搜索队伍信息
     *
     * @param teamProfileRequest
     * @return
     * @throws ParameterException
     * @throws Exception
     */
    @Override
    public Page<TeamProfile> getTeamByConditions(TeamProfileRequest teamProfileRequest) throws ParameterException, Exception {
        int size = teamProfileRequest.getSize();
        int current = teamProfileRequest.getCurrent();
        int notSignUp = teamProfileRequest.getNotSignUp();
        int isMembersShortage = teamProfileRequest.getIsMembersShortage();
        int notCutoff = teamProfileRequest.getNotCutoff();
        Long uid = teamProfileRequest.getUid() == null ? 0l : teamProfileRequest.getUid();
        String projectName = teamProfileRequest.getProjectName();
        String kw = teamProfileRequest.getKw();
//            参数检验
        if (current == 0 || size == 0) {
            throw new ParameterException("分页参数无效");
        }
        if (notSignUp == 1 && (uid <= 0l || String.valueOf(uid).length() != 12)) {
            throw new ParameterException("uid非法");
        }
//                保持teamProfileRequest非空
        if (teamProfileRequest == null) {
            teamProfileRequest = new TeamProfileRequest();
        }
        LambdaQueryWrapper<TeamProfile> lambdaQueryWrapper = new LambdaQueryWrapper<TeamProfile>();
        Page<TeamProfile> page = new Page(current, size);
//                对projectName设置条件查询
        if (projectName != null && (!projectName.equals(""))) {
            if (!projectName.equals("全部")) {
                String newProjectName = stringUtils.splitWordsForSearch(projectName);
                lambdaQueryWrapper.like(TeamProfile::getTpProjectName, newProjectName);
            }
        }
//                对TeamName和TeamIntro和projectName设置关键词的条件查询
        if (kw != null && (!kw.equals("")) && kw.length() > 0) {
            lambdaQueryWrapper.and(wq -> {
                String newkw = stringUtils.splitWordsForSearch(kw);
                wq.like(TeamProfile::getTpTeamName, newkw)
                        .or().like(TeamProfile::getTpTeamIntro, newkw)
                        .or().like(TeamProfile::getTpProjectName, newkw);
            });
        }
//               查询未满人的队伍
        if (isMembersShortage == 1) {
            lambdaQueryWrapper.gt(TeamProfile::getTpDifference, 0);
        }
//                查询未截止的招募
        if (notCutoff == 1) {
            // 获取当前日期
            LocalDate currentDate = LocalDate.now();
            // 判断当前日期是否在 `tp_registration_deadline` 日期之前
            lambdaQueryWrapper.ge(TeamProfile::getTpRegistrationDeadline, currentDate);
        }
        // 未截止、未满人的优先呈现
        lambdaQueryWrapper.orderByDesc(TeamProfile::getTpRegistrationDeadline);
        lambdaQueryWrapper.orderByDesc(TeamProfile::getTpDifference);
        //list1为一般条件查询后的结果
        List<TeamProfile> list1 = teamProfileDao.selectList(lambdaQueryWrapper);
        if (list1 != null && list1.size() > 0) {
            page = new PageMessage<TeamProfile>(current, size).pageForList(list1);
            //  将page的数据进行alive筛选
            page.setRecords(selectAliveTeam(page.getRecords()));
//                查询未报名的队伍
            if (notSignUp == 1) {
                //   list2为uid不在的队伍的结果
                List<TeamProfile> list2 = getNotInTeam(uid, current, size);
                //  finalList为list1和list2共有的搜索结果
                List<TeamProfile> finalList = list2.stream()
                        .flatMap(teamProfile2 -> {
                            Optional<TeamProfile> duplicate = list1.stream()
                                    .filter(teamProfile1 -> teamProfile2.getTpId().equals(teamProfile1.getTpId()))
                                    .findFirst();
                            if (duplicate.isPresent()) {
                                return Stream.of(duplicate.get());
                            } else {
                                return Stream.empty();
                            }
                        })
                        .collect(Collectors.toList());
                if (finalList != null && finalList.size() > 0) {
                    finalList = selectAliveTeam(finalList);
                    page = new PageMessage<TeamProfile>(current, size).pageForList(finalList);
                    //  将page的数据进行alive筛选
                    page.setRecords(selectAliveTeam(page.getRecords()));
                } else {
                    return null;
                }
            }
        }
        return page;
    }

    /**
     * 发布组建队伍信息（插入TeamProfile并且TeamComposition插入该用户作为队长）
     *
     * @param teamProfile
     * @param uid
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public String organizeTeam(TeamProfile teamProfile, Long uid) throws Exception {
        try {
//        保证id为空，在数据库自增长赋予id
            teamProfile.setTpId(null);
//            设置活跃状态
            teamProfile.setTpAlive(1);
//        调用isQualified()检查必要信息是否填写
            if (teamProfile.isQualified() && uid != null && uid > 0l) {
                teamProfile.setTpUid(uid);
//            查询数据库检查当前队伍名是否已存在
                LambdaQueryWrapper<TeamProfile> nameWrapper = new LambdaQueryWrapper<>();
                nameWrapper.eq(TeamProfile::getTpTeamName, teamProfile.getTpTeamName());
                Long oldNum = teamProfileDao.selectCount(nameWrapper);
                if (oldNum > 0l) {
                    return "队伍名已存在，请修改后重新尝试";
                }
//                根据uid查找当前用户
                String uname = userDao.selectRealNameByUid(uid);
                if (uname != null && !uname.equals("")) {
                    teamProfile.setTpUrealname(uname);
//                  插入新记录
                    int isSucceed = teamProfileDao.insert(teamProfile);
                    if (isSucceed > 0) {
                        //  得到新记录的队伍信息
                        LambdaQueryWrapper<TeamProfile> newWrapper = new LambdaQueryWrapper<>();
                        newWrapper.eq(TeamProfile::getTpTeamName, teamProfile.getTpTeamName());
                        TeamProfile newTeam = teamProfileDao.selectOne(newWrapper);
                        //  创建TeamComposition信息
                        TeamComposition teamComposition = new TeamComposition();
                        teamComposition.setTeamId(newTeam.getTpId());
                        teamComposition.setUid(newTeam.getTpUid());
                        teamComposition.setUrealname(newTeam.getTpUrealname());
                        teamComposition.setMemberType(1);
                        //  将新队伍队长的信息插入成员表中
                        int succeed = teamCompositionDao.insert(teamComposition);
                        return succeed > 0 ? "队伍组建成功" : "队伍组建失败";
                    }
                }
                return "队伍组建失败";
            }
            return "请检查是否正确填写必要信息";
        } catch (Exception e) {
            System.out.println(e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//回滚
            return "请检查信息是否填写正确";
        }
    }

    /**
     * 修改队伍基本信息
     *
     * @param teamProfile
     * @param uid
     * @return
     * @throws Exception
     */
    @Override
    public String modifyTeamMsg(TeamProfile teamProfile, Long uid) throws Exception {
//        先检验队伍信息是否填写完成(tpId)
        if (teamProfile.getTpId() != null && teamProfile.getTpId() > 0l) {
//            得到当前队伍原信息，检查是否为该用户所在的队伍（权限检查）
            LambdaQueryWrapper<TeamProfile> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(TeamProfile::getTpId, teamProfile.getTpId());
//            从数据库得到当前队伍信息
            TeamProfile teamProfile1 = teamProfileDao.selectOne(lambdaQueryWrapper);
            if (teamProfile1 != null && teamProfile1.getTpUid().equals(uid)) {
//                检查身份权限
                if (authorityUtils.qualifiedToModify(teamProfile.getTpId(), uid)) {
                    teamProfile.setTpAlive(1);
                    int isSucceed = teamProfileDao.updateById(teamProfile);
                    return isSucceed > 0 ? "队伍信息修改成功!" : "队伍信息修改失败";
                }
            }
            return "无权限修改队伍信息";
        }
        return "请检查是否正确填写必要信息";
    }

    /**
     * 解散队伍
     *
     * @param tpId
     * @param uid
     * @return
     * @throws ParameterException
     * @throws Exception
     */
    @Override
    public String dismissTeam(Long tpId, Long uid) throws ParameterException, Exception {
        if (uid == null || uid < 0l) {
            throw new ParameterException("uid为空或格式错误");
        }
        if (tpId == null || tpId < 0l) {
            throw new ParameterException("tpId为空或格式错误");
        }
        //检查身份权限
        boolean isQualifyToModify = authorityUtils.qualifiedToModify(tpId, uid);
        if (isQualifyToModify) {
            //检查当前队伍状态
            LambdaQueryWrapper<TeamProfile> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(TeamProfile::getTpId, tpId);
            TeamProfile teamProfile = teamProfileDao.selectOne(wrapper);
            if (teamProfile != null && teamProfile.getTpAlive() == 1) {
                //注销队伍
                int modify = teamProfileDao.updateTeamNotAlive(tpId);
                return modify > 0 ? "队伍解散成功" : "队伍解散失败";
            }
        }
        return "非指导老师、队长无权解散队伍";
    }

    /**
     * 筛选出列表中alive==1的队伍
     *
     * @param list
     * @return
     */
    public List<TeamProfile> selectAliveTeam(List<TeamProfile> list) {
        if (list != null && list.size() > 0) {
            List<TeamProfile> list1 = list.stream()
                    .filter(teamProfile -> teamProfile.getTpAlive() == 1)
                    .collect(Collectors.toList());
            return list1;
        }
        return null;
    }


}
